﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Asol.Reporting.Support;

namespace Asol.Reporting.Green
{
    public class TemplateInfo
    {
        #region Property a vizualizace
        /// <summary>
        /// Číslo šablony
        /// </summary>
        public int TemplateNumber { get; private set; }
        /// <summary>
        /// Název šablony uživatelský
        /// </summary>
        public string Name { get; private set; }
        /// <summary>
        /// Popis šablony
        /// </summary>
        public string Description { get; private set; }
        /// <summary>
        /// Číslo třídy
        /// </summary>
        public int ClassNumber { get; private set; }
        /// <summary>
        /// Název PBL knihovny
        /// </summary>
        public string PblLibrary { get; private set; }
        /// <summary>
        /// Adresář PBL souborů (pro dohledávání obrázků)
        /// </summary>
        public string PblPath { get; private set; }
        /// <summary>
        /// Název dataokna v rámci PBL knihovny
        /// </summary>
        public string DwName { get; private set; }
        public bool ForceAsync { get; private set; }
        public int NumberOfCopies { get; private set; }
        public bool SuppressDialog { get; private set; }
        /// <summary>
        /// true pokud v systému existuje tabulka pro ukládání FRX šablon (lcs.frx_templates)
        /// </summary>
        public bool FrxTableExists { get; private set; }
        /// <summary>
        /// ID záznamu FRX šablony (lcs.frx_templates.id), nebo 0 pokud záznam neexistuje nebo neexistuje tabulka (viz this.FrxTableExists)
        /// </summary>
        public int FrxId { get; private set; }
        /// <summary>
        /// Obsah definice šablony v XML formátu, načtený z lcs.frx_templates.frx_report (pokud taková tabulka existuje a má řádek odpovídající šabloně)
        /// </summary>
        public string FrxContent { get; private set; }
        /// <summary>
        /// Překlady pro FrxContent, načtené z lcs.frx_templates.frx_message
        /// </summary>
        public string FrxMessage { get; private set; }
        /// <summary>
        /// true pokud obsahuje data v FrxContent
        /// </summary>
        public bool HasFrxContent { get { return !String.IsNullOrEmpty(this.FrxContent); } }
        /// <summary>
        /// Obsah definice šablony načtený z PBL knihovny, v případě kdy neexistuje definice this.FrxContent
        /// </summary>
        public string SrdContent { get; private set; }
        /// <summary>
        /// Překlady pro SrdContent, celý obsah načtený z MSG souboru stejného jména jako je this.PblLibrary
        /// </summary>
        public string SrdMessage { get; private set; }
        /// <summary>
        /// true pokud obsahuje data v SrdContent
        /// </summary>
        public bool HasSrdContent { get { return !String.IsNullOrEmpty(this.SrdContent); } }
        /// <summary>
        /// true pokud obsahuje odkaz na PBL report (PblLibrary) a dataokno (DwName). Neřeší jeho existenci.
        /// </summary>
        public bool HasPblLibrary { get { return !String.IsNullOrEmpty(this.PblLibrary) && !String.IsNullOrEmpty(this.DwName); } }
        /// <summary>
        /// Obsah definice (buď FrxContent, nebo SrdContent).
        /// </summary>
        public string Content { get { return (this.HasFrxContent ? this.FrxContent : (this.HasSrdContent ? this.SrdContent : null)); } }
        /// <summary>
        /// Překlady hlášek (podle existence FrxContent : FrxMessage, nebo podle existence SrdContent : SrdMessage).
        /// </summary>
        public string Message { get { return (this.HasFrxContent ? this.FrxMessage : (this.HasSrdContent ? this.SrdMessage : null)); } }
        /// <summary>
        /// Vizualizace: "Name (number)"
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.Name + " (" + this.TemplateNumber.ToString() + ")";
        }
        #endregion
        #region Načtení záznamu/seznamu záznamů z databáze
        /// <summary>
        /// Vrátí true, pokud daná šablona existuje.
        /// </summary>
        /// <param name="templateNumber"></param>
        /// <returns></returns>
        public static bool Exists(int templateNumber)
        {
            string sql = SqlCommandLite + SqlWhereTemplate + templateNumber.ToString();
            using (Asol.Reporting.Support.Data.Table data = DbConnect.LoadTable(sql))
            {
                if (data.RowCount > 0)
                    return true;
            }
            return false;
        }
        /// <summary>
        /// Načte a vrátí instanci TemplateInfo pro jeden konkrétní záznam.
        /// Pokud záznam neexistuje, vyhodí chybu.
        /// </summary>
        /// <param name="templateNumber"></param>
        /// <returns></returns>
        public static TemplateInfo LoadTemplate(int templateNumber)
        {
            bool existsFrxTable = App.IsDbTableExists("lcs.frx_templates");
            string sql = (existsFrxTable ? SqlCommandFull : SqlCommandLite) + SqlWhereTemplate + templateNumber.ToString();
            using (Asol.Reporting.Support.Data.Table data = DbConnect.LoadTable(sql))
            {
                if (data.RowCount == 0)
                    throw new AdminException("Nelze načíst data šablony číslo %0, záznam v tabulce nebyl nalezen.");
                return new TemplateInfo(data.Rows[0]);
            }
        }
        /// <summary>
        /// Pokusí se najít a načíst instanci TemplateInfo pro jeden konkrétní záznam.
        /// Pokud záznam existuje, načte jej a vrátí true.
        /// Pokud neexistuje, vrátí false (a v templateInfo bude null).
        /// </summary>
        /// <param name="templateNumber"></param>
        /// <returns></returns>
        public static bool TryLoadTemplate(int templateNumber, out TemplateInfo templateInfo)
        {
            templateInfo = null;
            bool existsFrxTable = App.IsDbTableExists("lcs.frx_templates");
            string sql = (existsFrxTable ? SqlCommandFull : SqlCommandLite) + SqlWhereTemplate + templateNumber.ToString();
            using (Asol.Reporting.Support.Data.Table data = DbConnect.LoadTable(sql))
            {
                if (data.RowCount > 0)
                {
                    templateInfo = new TemplateInfo(data.Rows[0]);
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// Načte seznam všech šablon jedné dané třídy
        /// </summary>
        /// <param name="classNumber"></param>
        /// <returns></returns>
        public static List<TemplateInfo> LoadTemplates(int classNumber)
        {
            bool existsFrxTable = App.IsDbTableExists("lcs.frx_templates");
            string sql = (existsFrxTable ? SqlCommandFull : SqlCommandLite) + SqlWhereList + SqlAndCisloTridy + classNumber.ToString() + SqlOrderByListNazev;
            List<TemplateInfo> list = new List<TemplateInfo>();
            using (Asol.Reporting.Support.Data.Table data = DbConnect.LoadTable(sql))
            {
                foreach (var row in data.Rows)
                    list.Add(new TemplateInfo(row));
            }
            return list;
        }
        /// <summary>
        /// Privátní konstruktor pro načtená data
        /// </summary>
        /// <param name="row"></param>
        private TemplateInfo(Asol.Reporting.Support.Data.Row row)
        {
            this.TemplateNumber = row["cislo_template"].ValueInteger32;
            this.Name = row["nazev"].ValueCharacter;
            this.Description = row["popis"].ValueCharacter;
            this.ClassNumber = row["cislo_tridy"].ValueInteger32;
            this.PblLibrary = row["nazev_pbl"].ValueCharacter;
            this.DwName = row["nazev_dw"].ValueCharacter;
            this.ForceAsync = row["force_async"].ValueBoolean;
            this.NumberOfCopies = row["pocet_kopii"].ValueInteger32;
            this.SuppressDialog = row["potlacit_dialogove_okno"].ValueBoolean;
            this.FrxTableExists = row["frx_table_exists"].ValueBoolean;
            this.FrxId = row["id"].ValueInteger32;
            this.FrxContent = row["frx_report"].ValueCharacter;
            this.FrxMessage = row["frx_message"].ValueCharacter;

            this.PblPath = App.Settings.ActiveServer.ReportPath;
        }
        /// <summary>
        /// Privátní konstruktor pro prázdný záznam
        /// </summary>
        /// <param name="row"></param>
        private TemplateInfo(int classNumber)
        {
            this.TemplateNumber = 0;
            this.Name = "";
            this.Description = "";
            this.ClassNumber = classNumber;
            this.PblLibrary = null;
            this.DwName = null;
            this.ForceAsync = false;
            this.NumberOfCopies = 1;
            this.SuppressDialog = false;
            this.FrxTableExists = App.IsDbTableExists("lcs.frx_templates");
            this.FrxId = 0;
            this.FrxContent = "";
            this.FrxMessage = "";

            this.PblPath = App.Settings.ActiveServer.ReportPath;
        }
        #endregion
        #region SQL příkaz a jeho fráze
        /// <summary>
        /// Obsahuje SQL SELECT pro načtení dat šablony. Pracuje s tabulkami lcs.template (Green view) + lcs.frx_templates (FRX data). Neobsahuje keyword WHERE ani ORDER BY.
        /// Doplňte z SqlWhereTemplate, SqlWhereList, SqlOrderByListPblDw nebo SqlOrderByListNazev.
        /// </summary>
        public static string SqlCommandFull
        {
            get
            {
                return @"SELECT t.cislo_template, t.nazev, t.cislo_tridy, t.nazev_dw, t.nazev_pbl, t.popis, t.force_async, t.pocet_kopii, t.potlacit_dialogove_okno, 1 as frx_table_exists, f.id, f.frx_report, f.frx_message
FROM lcs.template t LEFT OUTER JOIN lcs.frx_templates f on f.cislo_template = t.cislo_template"; 
            }
        }
        /// <summary>
        /// Obsahuje SQL SELECT pro načtení dat šablony. Pracuje pouze s tabulkou lcs.template (Green view), nikoli s lcs.frx_templates (FRX data). Neobsahuje keyword WHERE ani ORDER BY.
        /// Doplňte z SqlWhereTemplate, SqlWhereList, SqlOrderByListPblDw nebo SqlOrderByListNazev.
        /// </summary>
        public static string SqlCommandLite
        {
            get
            {
                return @"SELECT t.cislo_template, t.nazev, t.cislo_tridy, t.nazev_dw, t.nazev_pbl, t.popis, t.force_async, t.pocet_kopii, t.potlacit_dialogove_okno, 0 as frx_table_exists, 0 as id, '' as frx_report, '' as frx_message
FROM lcs.template t"; 
            }
        }
        /// <summary>
        /// Obsahuje frázi " WHERE t.cislo_template = ", doplňte číslo šablony.
        /// </summary>
        public static string SqlWhereTemplate { get { return @" WHERE t.cislo_template = "; } }
        /// <summary>
        /// Obsahuje frázi " WHERE ...", která vyfiltruje jen šablony skutečně tiskové (PB).
        /// Pro šablony jen jedné třídy je třeba doplnit frázi SqlAndCisloTridy.
        /// </summary>
        public static string SqlWhereList { get { return @" WHERE t.typ = 'T' and charindex('.pbl', lower(t.nazev_pbl), 0) > 0 and t.cislo_tridy > 0"; } }
        /// <summary>
        /// Obsahuje frázi " and t.cislo_tridy = ", která vyfiltruje jen šablony konkrétní třídy. Typicky se doplňuje za SqlWhereList.
        /// Pro šablony jen jedné třídy je třeba doplnit frázi SqlAndCisloTridy.
        /// </summary>
        public static string SqlAndCisloTridy { get { return @" and t.cislo_tridy = "; } }
        /// <summary>
        /// Obsahuje frázi " ORDER BY t.nazev_pbl, t.nazev_dw" pro třídění dle názvu datawindow
        /// </summary>
        public static string SqlOrderByListPblDw { get { return @" ORDER BY t.nazev_pbl,t.nazev_dw"; } }
        /// <summary>
        /// Obsahuje frázi " ORDER BY t.nazev" pro třídění dle názvu šablony
        /// </summary>
        public static string SqlOrderByListNazev { get { return @" ORDER BY t.nazev"; } }
        /// <summary>
        /// Obsahuje SQL CREATE TABLE pro vytvoření tabulky lcs.frx_templates.
        /// Obsahuje i příkazy GO, protože v druhé dávce grantuje přístup k objektům.
        /// </summary>
        public static string SqlCreateFrxTable
        {
            get
            {
                return @"-- Create a new table for storing data for frx reports:
IF not exists(select * from sys.tables where object_id = object_id('lcs.frx_templates'))
 BEGIN
	CREATE TABLE lcs.frx_templates
	(
		[id] [int] IDENTITY(1,1) NOT NULL,
		[cislo_template] [int] NOT NULL,
		[frx_report] [nvarchar](max) NULL,
		[frx_message] [nvarchar](max) NULL,
		CONSTRAINT [PK_frx_templates_1] PRIMARY KEY NONCLUSTERED ([id] ASC) 
		WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 99) ON [PRIMARY]
	) ON [PRIMARY]
 END
GO

GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE ON lcs.frx_templates TO netadmin
GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE ON lcs.frx_templates TO netuser
GO";
            }
        }
        #endregion
        #region Podpora pro práci s reportem: donačtení SRD z PBL knihovny, tvorba objektu ReportDocument
        /// <summary>
        /// Ze svých dat vytvoří ReportDocument a vrátí jej. Pokud se to nepodaří, vyhodí chybu.
        /// </summary>
        /// <returns></returns>
        public Asol.Reporting.Editor.Data.ReportDocument CreateReportDocument()
        {
            if (!this.HasFrxContent)
                this.LoadSrdContent();

            Asol.Reporting.Editor.Data.ReportDocument document = Editor.Data.ReportDocument.CreateFromContent(this.Content);

            return document;
        }
        /// <summary>
        /// Zajistí editaci této šablony: vytvoří ReportDocument a zavolá jeho metodu ReportEdit().
        /// </summary>
        public void ReportEdit()
        {
            Asol.Reporting.Editor.Data.ReportDocument document = this.CreateReportDocument();
            document.ReportEdit();
        }
        /// <summary>
        /// Načte obsah Powerbuilder dataokna z PBL knihovny.
        /// Pokud to nejde, vyhodí chybu.
        /// </summary>
        public void LoadSrdContent()
        {
            if (!this.HasPblLibrary)
                throw new DevException("Šablona %0: %1 neobsahuje název PBL knihovny a/nebo název datawindow.", this.TemplateNumber, this.Name);

            string pblFile = System.IO.Path.Combine(this.PblPath, this.PblLibrary);
            this.SrdContent = Assistant.PblLibraryRead(pblFile, this.DwName);

            string msgFile = System.IO.Path.ChangeExtension(pblFile, "msg") + ".xml";
            this.SrdMessage = (System.IO.File.Exists(msgFile) ? System.IO.File.ReadAllText(msgFile, Encoding.UTF8) : "");
        }
        #endregion
    }
}
